﻿using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.DependencyInjection;
using My.Core.Util;
using My.Framework;
using My.Framework.AspNetCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace My.Core.SignalR
{
	public class SignalRStartup : StartupModule<SignalRStartup>
	{
		/// <summary>
		/// 程序启动器
		/// </summary>
		public SignalRStartup() => Order = 1;

		/// <summary>
		/// 
		/// </summary>
		/// <param name="webApplicationBuilder"></param>
		public override void ConfigureServices(WebApplicationBuilder webApplicationBuilder)
		{
			var services = webApplicationBuilder.Services;
			//注入SignalR实时通讯，默认用json传输
			services.AddSignalR(options =>
			{
				//客户端发保持连接请求到服务端最长间隔，默认30秒，改成4分钟，网页需跟着设置connection.keepAliveIntervalInMilliseconds = 12e4;即2分钟
				//options.ClientTimeoutInterval = TimeSpan.FromMinutes(4);
				//服务端发保持连接请求到客户端间隔，默认15秒，改成2分钟，网页需跟着设置connection.serverTimeoutInMilliseconds = 24e4;即4分钟
				//options.KeepAliveInterval = TimeSpan.FromMinutes(2);
			});

		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="webApplication"></param>
		public override void Configure(WebApplication webApplication)
		{
			var assemblyList = AssemblyUtil.GetAssemblyList().ToList();
			IEnumerable<Type> EffectiveTypes = assemblyList.SelectMany(GetTypes);
			// 扫描所有集线器类型并且贴有 [MapHub] 特性且继承 Hub 或 Hub<>
			var hubs = EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass
				&& u.IsDefined(typeof(MapHubAttribute), true)
				&& (typeof(Hub).IsAssignableFrom(u) || u.HasImplementedRawGeneric(typeof(Hub<>))));

			if (!hubs.Any()) return;

			// 反射获取 MapHub 拓展方法
			var mapHubMethod = typeof(HubEndpointRouteBuilderExtensions).GetMethods().Where(u => u.Name == "MapHub" && u.IsGenericMethod && u.GetParameters().Length == 2).FirstOrDefault();
			if (mapHubMethod == null) return;

			foreach (Type hub in hubs)
			{
				// 解析集线器特性
				MapHubAttribute customAttribute = hub.GetCustomAttribute<MapHubAttribute>(inherit: true);

				// 注册集线器
				var hubEndpointConventionBuilder =
					mapHubMethod.MakeGenericMethod(hub).Invoke(null, new object[] { webApplication, customAttribute.Pattern }) as HubEndpointConventionBuilder;
			}
		}

		/// <summary>
		/// 加载程序集中的所有类型
		/// </summary>
		/// <param name="ass"></param>
		/// <returns></returns>
		private static IEnumerable<Type> GetTypes(Assembly ass)
		{
			var types = Array.Empty<Type>();

			try
			{
				types = ass.GetTypes();
			}
			catch
			{
				Console.WriteLine($"Error load `{ass.FullName}` assembly.");
			}

			return types.Where(u => u.IsPublic);
		}
	}
}
